﻿package com.bizmlib.ui.composite
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	
	import com.bizmlib.utils.ItemsArrangeManager;
	
	
	public class UICompositionArrangeManager extends EventDispatcher
	{
		public static const EVENT_HIDEMARKER_INVOKED:String = "hideMarkerInvoked";
		public static const EVENT_SHOWMARKER_INVOKED:String = "showMarkerInvoked";
		public static const EVENT_DRAG_CONFIRMED:String = "dragConfirmed";
		
		public static const ORIENTATION_NONE:String = "none";
		public static const ORIENTATION_HORIZONTAL:String = "horizontal";
		public static const ORIENTATION_VERTICAL:String = "vertical";
		
		public static const SELECTED_POSITION_CORRECTION_NONE:Number = 0;
		public static const SELECTED_POSITION_CORRECTION_INCREMENT:Number = 1;
		public static const SELECTED_POSITION_CORRECTION_DECREMENT:Number = 2;
		
		private static const STATE_NO_DRAG:Number = 10;
		private static const STATE_IS_DRAGGING:Number = 11;
		
		private var stateDrag:Number;
		private var composition:UIComposition;
		private var itemsArrangeManager:ItemsArrangeManager;
		private var __visibleItemsList:Array;
		private var __draggingItemIndex:Number;
		private var __selectedPosition:Number;
		private var correctionType:Number;
		
		public var handleOutsideDrop:Boolean;
		
		
		public function UICompositionArrangeManager(composition:UIComposition, orientation:String = undefined, correctionType:Number = undefined)
		{
			stateDrag = STATE_NO_DRAG;
			
			this.composition = composition;
			this.correctionType = correctionType || SELECTED_POSITION_CORRECTION_NONE;
			composition.addEventListener(UICompositionItemEvent.DRAG_INVOKED, itemDragInvoked);
			
			instantiateItemsArrangeManager(orientation);
		}
		
		
		public function set visibleItemsList(value:Array):void
		{
			__visibleItemsList = value;
		}
		public function get visibleItemsList():Array
		{
			return __visibleItemsList;
		}
		
		public function get draggingItemIndex():Number
		{
			return __draggingItemIndex;
		}
		public function get selectedPosition():Number
		{
			return __selectedPosition;
		}
		
		
		public function clear():void
		{
			composition.stage.removeEventListener(MouseEvent.MOUSE_MOVE, arrangeMouseMove);
			composition.stage.removeEventListener(MouseEvent.MOUSE_UP, arrangeMouseUp);
			
			composition.removeEventListener(UICompositionItemEvent.DRAG_INVOKED, itemDragInvoked);
			composition = null;
			
			itemsArrangeManager.itemsList = null;
			itemsArrangeManager = null;
			
			visibleItemsList = null;
		}
		public function dragEmptyItem():void
		{
			itemsArrangeManager.draggingItemIndex = Number.NaN;
			
			startItemDrag();
		}
		public function stopItemDrag(noEvent:Boolean = true):void
		{
			completeItemDrag(noEvent);
		}
		
		
		protected function instantiateItemsArrangeManager(orientation:String = undefined):void
		{
			itemsArrangeManager = new ItemsArrangeManager(orientation);
		}
		protected function itemDragInvoked(event:UICompositionItemEvent):void
		{
			//trace(this + ".itemDragInvoked(" + arguments + ")");
			//trace(event.target);
			
			//event.stopImmediatePropagation();
			
			var item:UICompositionItem = event.item;
			
			for(var i:Number=0; i<visibleItemsList.length; i++)
			{
				if(visibleItemsList[i] == item)
				{
					__draggingItemIndex = i;
					itemsArrangeManager.draggingItemIndex = i;
					break;
				}
			}
			
			startItemDrag();
		}
		protected function startItemDrag():void
		{
			if(stateDrag!=STATE_NO_DRAG)
			{
				return;
			}
			stateDrag = STATE_IS_DRAGGING;
			
			__selectedPosition = undefined;
			
			composition.stage.addEventListener(MouseEvent.MOUSE_MOVE, arrangeMouseMove);
			composition.stage.addEventListener(MouseEvent.MOUSE_UP, arrangeMouseUp);
			
			itemsArrangeManager.itemsList = visibleItemsList;
		}
		protected function completeItemDrag(noEvent:Boolean = false):void
		{
			if(stateDrag!=STATE_IS_DRAGGING)
			{
				return;
			}
			stateDrag = STATE_NO_DRAG;
			
			dispatchEvent(new Event(EVENT_HIDEMARKER_INVOKED, false, false));
			
			composition.stage.removeEventListener(MouseEvent.MOUSE_MOVE, arrangeMouseMove);
			composition.stage.removeEventListener(MouseEvent.MOUSE_UP, arrangeMouseUp);
			
			if(selectedPosition==draggingItemIndex)
			{
				//...
			}
			else if(!isNaN(selectedPosition) && !noEvent)
			{
				switch(correctionType)
				{
					case SELECTED_POSITION_CORRECTION_INCREMENT:
						if(!isNaN(draggingItemIndex) && (selectedPosition > draggingItemIndex))
						{
							__selectedPosition--;
						}
						break;
					case SELECTED_POSITION_CORRECTION_DECREMENT:
						if(!isNaN(draggingItemIndex) && (selectedPosition < draggingItemIndex))
						{
							__selectedPosition++;
						}
						break;
				}
				dispatchEvent(new Event(EVENT_DRAG_CONFIRMED, false, false));
			}
			else if(isNaN(selectedPosition) && !noEvent && handleOutsideDrop)
			{
				dispatchEvent(new Event(EVENT_DRAG_CONFIRMED, false, false));
			}
			
			__draggingItemIndex = undefined;
		}
		protected function arrangeMouseMove(event:MouseEvent):void
		{
			//trace(this + ".arrangeMouseMove(" + arguments + ")");
			
			var positionIndex:Number = itemsArrangeManager.calculatePositionIndex(composition.mouseX, composition.mouseY);
			//trace("positionIndex=" + positionIndex);
			if(isNaN(positionIndex))
			{
				if(handleOutsideDrop)
				{
					__selectedPosition = undefined;
					dispatchEvent(new Event(EVENT_HIDEMARKER_INVOKED, false, false));
				}
				return;
			}
			else if(positionIndex==draggingItemIndex)
			{
				__selectedPosition = undefined;
				__selectedPosition = positionIndex;
				dispatchEvent(new Event(EVENT_HIDEMARKER_INVOKED, false, false));
				return;
			}
			
			switch(correctionType)
			{
				case SELECTED_POSITION_CORRECTION_INCREMENT:
					if(!isNaN(draggingItemIndex) && (positionIndex > draggingItemIndex))
					{
						positionIndex++;
					}
					break;
				case SELECTED_POSITION_CORRECTION_DECREMENT:
					if(!isNaN(draggingItemIndex) && (positionIndex < draggingItemIndex))
					{
						positionIndex--;
					}
					break;
			}
			__selectedPosition = positionIndex;
			
			dispatchEvent(new Event(EVENT_SHOWMARKER_INVOKED, false, false));
		}
		protected function arrangeMouseUp(event:MouseEvent):void
		{
			completeItemDrag();
		}
		
		
		override public function toString():String
		{
			return "[UICompositionArrangeManager	composition:" + composition + "]";
		}
	}
}